#include "util.h"

void daemonize(int keep_fd)
{
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);
	int i, pid;
	// parent
	if((pid = fork()))
		exit(0);
	// fork fail and exit
	else if(pid < 0)
		exit(1);

	setsid();
	signal(SIGHUP, SIG_IGN);
	if((pid = fork()))
		exit(0);
	else if(pid < 0)
		exit(1);

	if(0 == keep_fd)
	{
		for(i=0; i<255; i++)
			close(i);
	}
	umask(0);
	return;
}

int write_pid_to_file(const char* pid_file)
{
	if (!pid_file)
	{
		fprintf(stderr, "no pid file to write!\n");
		return -1;
	}

	int fd = open(pid_file, O_CREAT | O_TRUNC | O_RDWR, 0666);
	if(fd < 0)
	{
		fprintf(stderr, "open(create) pid file[%s] fail!\n", pid_file);
		return -1;
	}

	// lock pid file
	if(0 != flock(fd, LOCK_EX | LOCK_NB))
	{
		fprintf(stderr, "lock to pid file[%s] fail!\n", pid_file);
		close(fd);
		return -1;
	}

	char pidstr[16];
	memset(pidstr, 0, sizeof(pidstr));
	snprintf(pidstr, sizeof(pidstr), "%d", getpid());
	int len = strlen(pidstr);
	if (len != write(fd, pidstr, len))
	{
		fprintf(stderr, "write pid file[%s] fail!\n", pid_file);
		close(fd);
		return -1;
	}
	close(fd);
	return 0;
}

int read_pid_from_file(const char* pid_file)
{
	if(!pid_file)
	{
		fprintf(stderr, "no pid file to read!\n");
		return -1;
	}

	int fd = open(pid_file, O_RDONLY, 0644);
	if (fd < 0)
	{
		fprintf(stderr, "open pid file[%s] fail!\n", pid_file);
		return -1;
	}

	char pidstr[16];
	memset(pidstr, 0, 16);
	if (-1 == read(fd, pidstr, sizeof(pidstr)))
	{
		fprintf(stderr, "read pid file[%s] fail!\n", pid_file);
		close(fd);
		return -1;
	}

	close(fd);
	return atoi(pidstr);
}

int process_exist(const char* pid_file, const char* proc_name)
{
	if (!proc_name || !pid_file)
	{
		fprintf(stderr, "pid file or proc name invalid fail\n");
		return -1;
	}

	/* read pid */
	int pid = read_pid_from_file(pid_file);
	if(pid < 0) return -1;

	/* check /proc/pid */
	char proc_dir[256];
	snprintf(proc_dir, sizeof(proc_dir), "/proc/%d", pid);
	struct stat stat_data;
	int ret = stat(proc_dir, &stat_data);
	if (ret < 0 || !S_ISDIR(stat_data.st_mode))
		return -1;

	/* exist */
	return 0;
}

void get_timestamp(struct timeval* time, char* stamp)
{
	struct tm now_tm;
	localtime_r(&time->tv_sec, &now_tm);
	sprintf(stamp, "[%d-%02d-%02d %02d:%02d:%02d:%06d]", 
		now_tm.tm_year + 1900,
		now_tm.tm_mon + 1,
		now_tm.tm_mday,
		now_tm.tm_hour,
		now_tm.tm_min,
		now_tm.tm_sec,
		time->tv_usec);
}

void get_timestamp_suffix(struct timeval* time, char* stamp)
{
	struct tm now_tm;
	localtime_r(&time->tv_sec, &now_tm);
	sprintf(stamp, "%d%02d%02d_%02d_%02d_%02d_%06d", 
		now_tm.tm_year + 1900,
		now_tm.tm_mon + 1,
		now_tm.tm_mday,
		now_tm.tm_hour,
		now_tm.tm_min,
		now_tm.tm_sec,
		time->tv_usec);
}

uint32_t get_hour_number(time_t time)
{
	struct tm now_tm;
	localtime_r(&time, &now_tm);	
	return (uint32_t)(now_tm.tm_year + 1900) * 1000000
		+ (uint32_t)(now_tm.tm_mon + 1) * 10000 
		+ (uint32_t)now_tm.tm_mday * 100
		+ (uint32_t)now_tm.tm_hour;
}

uint32_t get_date_number(time_t time)
{
	struct tm now_tm;
	localtime_r(&time, &now_tm);	
	return (uint32_t)(now_tm.tm_year + 1900) * 10000
		+ (uint32_t)(now_tm.tm_mon + 1) * 100 
		+ (uint32_t)now_tm.tm_mday;
}

